package com.zjl.SpringBoot.第06章_基本特性;

import com.zjl.SpringBoot.SpringBootMainApplication;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.Charset;

/**
 * 外部配置  在 xxx.jar 所在文件夹下放一个
 *      application.properties
 *  就会自动以此  文件为准
 *
 * 配置优先级
 *      Spring Boot允许将配置外部化，以便可以在不同的环境中使用相同的应用程序代码
 *      可以使用各种外部配置源，包括Java Properties文件、YAML文件、环境变量和命令行参数
 *
 * SpringBoot属性源  加载顺序
 *      以下顺序优先级由**低到高**，高优先级配置覆盖低优先级【后面的会覆盖前面的值】
 *      1.默认属性（通过SpringApplication.setDefaultProperties指定的）
 *      2.@PropertySource 加载指定的配置文件（需要写在@Configuration类上才可生效）
 *              如：@PropertySource("classpath:xxx.properties")
 *      3.配置文件（application.properties/yml等）
 *      4.RandomValuePropertySource支持的 random.*配置（如：@Value(“${random.int}”)）
 *      5.OS 环境变量
 *      6.Java 系统属性（System.getProperties()）
 *      7.JNDI 属性（来自java:comp/env）
 *      8.ServletContext 初始化参数
 *      9.ServletConfig 初始化参数
 *      10.SPRING_APPLICATION_JSON属性（内置在环境变量或系统属性中的 JSON）
 *      11.命令行参数     java -jar xxx.jar --server.port=9999 --spring.profiles.active=制定环境1,制定环境2
 *      12.测试属性(@SpringBootTest进行测试时指定的属性)
 *      13.测试类@TestPropertySource注解
 *      14.Devtools 设置的全局属性($HOME/.config/spring-boot)
 * 结论
 *      配置可以写到很多位置
 *      常见的优先级顺序：命令行> 配置文件> springapplication 配置
 * *********************************************************************************************************
 *  配置文件优先级
 *      从低到高，后面覆盖前面
 *      jar 包内的 application.properties/yml
 *      jar 包内的 application-{profile}.properties/yml
 *      jar 包外的 application.properties/yml
 *      jar 包外的 application-{profile}.properties/yml
 *  建议：用一种格式的配置文件，如果.properties和.yml同时存在，则.properties优先
 * 结论
 *      包外 > 包内
 *      同级情况下：{profile} 配置 > 默认 配置
 * *********************************************************************************************************
 * 外部配置
 * 顺序
 * SpringBoot 应用启动时会自动寻找 application.properties和application.yaml位置进行加载，
 *      顺序如下【由低到高】
 *      类路径：内部
 *              类根路径
 *              类下/config包
 *      当前路径（项目所在的位置）：外部
 *              当前路径
 *              当前下/config 目录
 *              /config/** 目录的直接子目录
 * 结论
 *      命令行 > 包外 config 直接子目录 > 包外 config 目录 > 包外根目录 > 包内目录
 *
 * 命令行 > 所有         包外 > 包内         config目录 > 根目录      profile > 默认
 * 同级比较         profile配置 > 默认配置        properties配置 > yaml配置
 * 配置不同就都生效（互补），配置相同高优先级覆盖低优先级
 * *********************************************************************************************************
 *
 * 导入配置
 * 使用spring.config.import可以导入额外配置，类似于@PropertySource
 *      spring.config.import=my.properties
 *      my.property=value
 * 无论以上写法的先后顺序，my.properties 的值总是优先于直接在文件中编写的 my.property
 * 【导入文件的优先级低于配置文件的优先级，因为外部大于内部，而且该方式的优先级和@PropertySource一样】
 *
 */
@Configuration
//@PropertySource("classpath:xxx.properties")
@SpringBootApplication(
        exclude = {DataSourceAutoConfiguration.class}
)
public class D_外部化配置环境变量 {
    public static void main(String[] args) {

        System.setProperty("spring.profiles.active","06");//  同理 --spring.profiles.active=xxx

        SpringApplication.run(D_外部化配置环境变量.class, args);
        System.err.println("***********启动完毕**当前编码:" + Charset.defaultCharset().name() + "****************");

        //流式 创建
//        new SpringApplicationBuilder()
//                .sources(B_自定义SpringApplication.class)
//                .properties("server.port=8888","aaa=bbb")
//                .run(args);

    }
}
@RestController
class demo{
    @Value("${dkh}")
    String dkh;
    @Value("${amt}")
    String amt;
    @GetMapping("/dkh")
    public String dkh(){
        return dkh;
    }
    @GetMapping("/amt")
    public String amt(){
        return amt;
    }
}
